package xyz.xtt.asset.service.impl;

import static xyz.xtt.common.asset.AssertUtils.isFalse;
import static xyz.xtt.common.asset.AssertUtils.isNull;
import static xyz.xtt.common.asset.AssertUtils.isTrue;

import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.primitives.Longs;

import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import xyz.xtt.asset.api.enums.SellPatternEnum;
import xyz.xtt.asset.api.enums.StatusAllEnum;
import xyz.xtt.asset.constants.AssetCache;
import xyz.xtt.asset.constants.ErrorMessage;
import xyz.xtt.asset.entity.TblAsset;
import xyz.xtt.asset.entity.TblAssetAccount;
import xyz.xtt.asset.entity.TblAssetExt;
import xyz.xtt.asset.entity.TblAssetNo;
import xyz.xtt.asset.entity.TblAssetUserLog;
import xyz.xtt.asset.mapper.TblAssetUserLogMapper;
import xyz.xtt.asset.request.OperateDownRequest;
import xyz.xtt.asset.request.OperateUpRequest;
import xyz.xtt.asset.service.IInnerService;
import xyz.xtt.asset.service.ITblAssetAccountService;
import xyz.xtt.asset.service.ITblAssetExtService;
import xyz.xtt.asset.service.ITblAssetNoService;
import xyz.xtt.asset.service.ITblAssetService;
import xyz.xtt.asset.service.ITblAssetTransactionService;
import xyz.xtt.asset.service.ITblAssetUserLogService;
import xyz.xtt.asset.vo.PreSellInfoVo;
import xyz.xtt.common.starter.cache.CacheManager;
import xyz.xtt.exchange.request.CopyrightRequest;

/**
 * <p>
 * 资产上下架操作表 服务实现类
 * </p>
 *
 * @author author
 * @since 2025-02-18
 */
@RefreshScope
@Slf4j
@Service
public class TblAssetUserLogServiceImpl extends ServiceImpl<TblAssetUserLogMapper, TblAssetUserLog> implements ITblAssetUserLogService {
	@Autowired
	private CacheManager cacheManager;

	/**
	 * 公示期 分钟数 15*24*60 = 21,600
	 */
	@Value("${asset.notice.period.minutes:21600}")
	private Long noticePeriodMinutes;
	/**
	 * c2c上架要标满足创建5天后才可以操作的条件
	 */
	@Value("${asset.mint.secondTypeShelfTimeMinutes:5}")
	private Long secondTypeShelfTimeMinutes;

	@Value("${asset.user.change.limit:10000}")
	private BigDecimal userChangeLimit;

	@Value("${asset.mint.canShelf:true}")
	private boolean canShelf;
	@Autowired
	private IInnerService iInnerService;
	@Autowired
	private ITblAssetTransactionService iTblAssetTransactionService;
	@Autowired
	private ITblAssetAccountService iTblAssetAccountService;

	@Autowired
	private ITblAssetNoService iAssetNoService;

	@Override
	public TblAssetUserLog lastConfigWithCache(Long assetId) {
		return cacheManager.cacheObj(() -> lastConfig(assetId), AssetCache.TBL_ASSET_USER_LOG, String.valueOf(assetId));
	}

	@Override
	public TblAssetUserLog lastConfig(Long assetId) {
		return new LambdaQueryChainWrapper<>(baseMapper)
				.eq(TblAssetUserLog::getAssetId, assetId)
				.orderByDesc(TblAssetUserLog::getCreateTime)
				.last("limit 1")
				.one();
	}

	@Autowired
	private ITblAssetService iTblAssetService;
	@Autowired
	private ITblAssetExtService iTblAssetExtService;

	private TblAsset checkAssetOwnerisMe(String uid, String goodsId) {
		TblAsset asset = iTblAssetService.assetInfoWithGoodsId(goodsId);
		isNull(asset, ErrorMessage.ASSET_NOT_EXIST);
//		isFalse(Objects.equals(asset.getOwnerId(), uid), ErrorMessage.ALLOWED_NOT_ME);
//		isFalse(asset.isMiner(uid), ErrorMessage.NOT_AN_MINER);
		isFalse(asset.isAssetNft(), ErrorMessage.NOT_OWNER_NFT_ASSET);
		return asset;
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public Boolean putOn(String uid, OperateUpRequest operateUpRequest) {
		Boolean reult = Boolean.FALSE;
		isFalse(canShelf, ErrorMessage.TOTAL_REQUSET_DAY_LIMIT);
		TblAsset asset = checkAssetOwnerisMe(uid, operateUpRequest.getGoodsId());
		// 判断资产不能售卖， 不能上架
		isFalse(asset.getSellable().equals(StatusAllEnum.YES.code()), ErrorMessage.ASSET_NOT_SELL_PATTERN);

		TblAssetAccount account = iTblAssetAccountService.account(asset.getId(), Longs.tryParse(uid));
		isNull(account, ErrorMessage.INSUFFICIENT_BALANCE);
		isTrue(operateUpRequest.getPrice() == null || operateUpRequest.getPrice().compareTo(new BigDecimal(1)) < 0, ErrorMessage.SELL_PRICE_EX);
		Long assetId = asset.getId();
		operateUpRequest.setAssetId(assetId);
		// 当前作为购买人相对应的交易是否上链
		TblAssetExt assetExt = iTblAssetExtService.info(assetId);
		isNull(assetExt, ErrorMessage.ASSET_NOT_EXIST);

		PreSellInfoVo preSellInfoVo = PreSellInfoVo.buildCalc(operateUpRequest, asset.getFirstType(), assetExt.checkPublicityPeriodEnd());
		isFalse(Objects.equals(account.getSellPattern(), SellPatternEnum.NORMAL.code()), ErrorMessage.ASSET_NOT_DOWN);
		BigDecimal price = operateUpRequest.getPrice();
		// 上架操作，计算公示期
		// 数量*单价 必须小于 10000
		String totalAmount = String.valueOf(asset.getAmount());
		BigDecimal totalMax = new BigDecimal(totalAmount).multiply(price);
		boolean result = totalMax.compareTo(userChangeLimit) > 0;
		isTrue(result, ErrorMessage.SELL_PRICE_EX, () -> log
				.info("totalMax:{},price:{},amount:{},userChangeLimit:{}", totalMax, price, totalAmount, userChangeLimit));
		// 一级交易 需要设置公示期
		if (asset.isTopTrade(uid)) {
			reult = iTblAssetExtService.updatePutOn(preSellInfoVo, noticePeriodMinutes, assetExt, operateUpRequest);
			isFalse(reult, ErrorMessage.ASSET_SETTING_EX);
		} else {
			// 校验价格
			log.info("putOn ctc param:{}", JSONUtil.toJsonStr(operateUpRequest));
			checkMinAndMax(uid, asset.getParentId(), price);
			isFalse(checkCanOnDate(operateUpRequest.getAssetId(), Long.valueOf(uid)), ErrorMessage.CREATED_DAYS_LIMIT);
		}
		// 版权声明
		// 方法被重构
//		saveCopyright(uid, operateUpRequest, asset);
		CopyrightRequest copyrightRequest = CopyrightRequest
				.builder()
				.assetId(assetId)
				.uid(uid)
				.copyrights(operateUpRequest.getCopyrights())
				.originalCopyrights(operateUpRequest.getOriginalCopyrights())
				.rootAssetId(asset.getRootAssetId())
				.authorId(asset.getAuthorId())
				.build();
		Boolean saveCopyright = iInnerService.saveCopyright(copyrightRequest);
		isFalse(saveCopyright, ErrorMessage.ASSET_SETTING_EX);
		// 设置 account\ asset_no 数据
		reult = iTblAssetAccountService.putOnc2cV2(operateUpRequest, Long.valueOf(uid));
		isFalse(reult, ErrorMessage.ASSET_SETTING_EX);
		TblAssetUserLog newConfig = operateUpRequest.buildTblAssetUserLog(uid, preSellInfoVo, noticePeriodMinutes, Boolean.TRUE, asset, assetExt);
		// 上架不需要操作 主表数据
		// boolean updateAssetPrice = iTblAssetService.updateAsset(assetId, price,
		// operateUpRequest.getGuidePirce(), SellPatternEnum.NORMAL,
		// SellPatternEnum.BUY_NOW_PRICE);
//		isFalse(updateAssetPrice, ErrorMessage.ASSET_SETTING_EX);
		boolean save = save(newConfig);
		isFalse(save, ErrorMessage.ASSET_SETTING_EX);
		clearCache(asset.getGoodsId(), uid, asset.getId());
		return save;
	}

	private Boolean checkCanOnDate(Long assetId, Long userId) {
		// 获取我的名下资产获取时间
		List<TblAssetNo> listByAssetId = iAssetNoService.getListByAssetId(assetId, userId, 1L);
		isTrue(listByAssetId.isEmpty(), ErrorMessage.ASSET_SETTING_EX);
		TblAssetNo tblAssetNo = listByAssetId.get(0);
		return System.currentTimeMillis() - tblAssetNo.getReceiveTime() >= TimeUnit.MINUTES.toMillis(secondTypeShelfTimeMinutes);
	}

//	private void saveCopyright(String uid, OperateUpRequest operateUpRequest, TblAsset asset) {
//		if (checkFirstBusiness(uid, asset)) {
//			if (checkPersonal(uid)) {
//				// 是个人
//				isTrue(CollectionUtil.isEmpty(operateUpRequest.getCopyrights())
//						&& CollectionUtil.isEmpty(operateUpRequest.getOriginalCopyrights()), ErrorMessage.COPYRIGHT_ORIGINAL_CANNOT_BE_EMPTY);
//			} else {
//				isTrue(CollectionUtil.isEmpty(operateUpRequest.getCopyrights()), ErrorMessage.COPYRIGHT_CANNOT_BE_EMPTY);
//			}
//			// 如果是商家 版权证明必填
//			// 如果是个人 至少要填一个类型
//			iInnerService.saveCopyright(asset.getId(), uid, 0, operateUpRequest.getCopyrights());
//			iInnerService.saveCopyright(asset.getId(), uid, 1, operateUpRequest.getOriginalCopyrights());
//		}
//	}

	/**
	 * 检查是否为一级交易
	 * 
	 * @param uid
	 * @param asset
	 * @return
	 */

	private Boolean checkFirstBusiness(String uid, TblAsset asset) {
		return Objects.equals(asset.getId(), asset.getRootAssetId()) && Objects.equals(asset.getAuthorId(), uid);
	}

	private Boolean checkPersonal(String uid) {
		return !iInnerService.judgeMerchantPer(uid);
	}

	private void checkMinAndMax(String uid, String goodsId, BigDecimal price) {
		BigDecimal buyMaxPriceWithHistory = iTblAssetTransactionService.buyMaxPriceWithHistory(uid, goodsId);
		isNull(buyMaxPriceWithHistory, ErrorMessage.MAX_PRICE_HISTORY_EX);
		BigDecimal diff = buyMaxPriceWithHistory.multiply(new BigDecimal("0.15"));
		BigDecimal min = buyMaxPriceWithHistory.subtract(diff);
		boolean result = price.compareTo(min) >= 0;
		isFalse(result, ErrorMessage.SELL_PRICE_EX, () -> log.info("min:{},buyMaxPrice:{},sellPrice:{}", min, buyMaxPriceWithHistory, price));
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public Boolean putOff(String uid, OperateDownRequest operateDownRequest) {
		TblAsset asset = checkAssetOwnerisMe(uid, operateDownRequest.getGoodsId());
		TblAssetExt assetExt = iTblAssetExtService.info(asset.getId());
		isNull(assetExt, ErrorMessage.ASSET_NOT_EXIST);
		// isFalse(Objects.equals(asset.getSellPattern(),
		// SellPatternEnum.BUY_NOW_PRICE.code()), ErrorMessage.ASSET_NOT_UP);
		TblAssetUserLog newConfig = new OperateUpRequest()
				.buildTblAssetUserLog(uid, PreSellInfoVo.buildDefault(), noticePeriodMinutes, Boolean.FALSE, asset, assetExt);
		boolean save = save(newConfig);
		isFalse(save, ErrorMessage.ASSET_SETTING_EX);
		if (assetExt.checkPublicityPeriod()) {
			// 公示期下架，把公示期置空
			boolean updatePutOffResult = iTblAssetExtService.updatePutOff(asset.getId());
			isFalse(updatePutOffResult, ErrorMessage.ASSET_SETTING_EX);
		}
		// 一级交易，修改公示期等数据 不处理
		if (asset.isTopTrade(uid)) {
			// boolean updateShowState = iTblAssetService.updateSellPattern(asset.getId(),
			// SellPatternEnum.BUY_NOW_PRICE, SellPatternEnum.NORMAL);
			// isFalse(updateShowState, ErrorMessage.ASSET_SETTING_EX);
		}
		// 处理 assetAccount assetNO数据
		boolean updateAssetAccount = iTblAssetAccountService.putOff(asset.getId(), Long.valueOf(uid));
		isFalse(updateAssetAccount, ErrorMessage.ASSET_SETTING_EX);
		clearCache(asset.getGoodsId(), uid, asset.getId());
		return Boolean.TRUE;
	}

	private void clearCache(String goodsId, String uid, Long assetId) {
		// 清除三个缓存
		cacheManager.delete(AssetCache.TBL_ASSET, goodsId);
		cacheManager.delete(AssetCache.TBL_ASSET_BY_ID, String.valueOf(assetId));
		cacheManager.delete(AssetCache.TBL_ASSET_EXT, String.valueOf(assetId));
		cacheManager.delete(AssetCache.TBL_ASSET_USER_LOG, String.valueOf(assetId));
	}

}
